package org.nkk.media.hook.service.impl;


import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.nkk.media.beans.constant.MediaEnum;
import org.nkk.media.beans.entity.ServerNodeConfig;
import org.nkk.media.hook.param.*;
import org.nkk.media.hook.service.ZlmHookService;
import org.nkk.sip.beans.model.base.ToDevice;
import org.nkk.sip.beans.model.invite.InviteStream;
import org.nkk.sip.core.sdp.GB28181SDPBuilder;
import org.nkk.sip.core.service.SipMessageTemplate;
import org.nkk.sip.core.session.impl.InviteManager;
import org.nkk.sip.core.session.impl.ProxyManager;

import javax.annotation.Resource;
import java.util.Objects;

/**
 * @author luna
 * @date 2023/12/5
 */

@Slf4j
public class DefaultZlmHookServiceImpl implements ZlmHookService {

    @Resource
    private SipMessageTemplate sipMessageTemplate;

    @Resource
    private InviteManager inviteManager;

    @Resource
    private ProxyManager proxyManager;

    @Override
    public void onServerKeepLive(OnServerKeepaliveHookParam param) {
        log.debug("「zlm_hook」心跳");
    }

    @Override
    public HookResult onPlay(OnPlayHookParam param) {
        return HookResult.SUCCESS();
    }

    @Override
    public HookResultForOnPublish onPublish(OnPublishHookParam param) {
        log.info("「zlm_hook」推流鉴权事件,\n {}",JSONObject.toJSONString(param));
        // 国标点播
        if (StringUtils.equalsIgnoreCase(MediaEnum.App.rtp.name(), param.getApp())) {
            InviteStream data = inviteManager.getData(param.getStream());
            if(Objects.isNull(data)){
                return HookResultForOnPublish.OK_EMPTY();
            }

            HookResultForOnPublish success = HookResultForOnPublish.ofCustom()
                    .setEnableRtmp(true)
                    .setEnableRecord(data.isEnableMp4Record())
                    .setRecordSplitTime(data.getMp4MaxSecond())
                    .build();
            // 认证成功
            inviteManager.processAuth(param);
            if (data.getAction().equalsIgnoreCase(GB28181SDPBuilder.Action.PLAY_BACK.getAction())) {
                success.setModifyStamp(2);
            }
            return success;
        }
        return HookResultForOnPublish.OK_EMPTY();

    }


    @Override
    public void onStreamChanged(OnStreamChangedHookParam param) {
        if (StringUtils.equalsIgnoreCase(MediaEnum.App.rtp.name(), param.getApp())) {
            if (param.isRegist()) {
                log.info("「zlm_hook」国标流注册");
                inviteManager.processOk(param.getStream());
            } else {
                log.info("「zlm_hook」国标流注销");
                inviteManager.releaseData(InviteManager.getKey(param.getStream()));
            }
        }
        // 代理无人观看
        else if (StringUtils.equalsIgnoreCase(MediaEnum.App.proxy.name(), param.getApp())) {
            if (param.isRegist()) {
                log.info("「zlm_hook」代理流注册");
                proxyManager.processOk(param.getStream(), param);
            } else {
                log.info("「zlm_hook」代理流注销");
                // 代理流设置的无限重试，注销后自动拉起。不能移除缓存数据
                // proxyManager.delData(param.getStream());
            }
        }

    }

    @Override
    public HookResultForStreamNoneReader onStreamNoneReader(OnStreamNoneReaderHookParam param) {
        log.info("「zlm_hook」无人观看:{}", StringUtils.joinWith("/", param.getApp(), param.getStream()));
        // 国标点播
        if (StringUtils.equalsIgnoreCase(MediaEnum.App.rtp.name(), param.getApp())) {
            InviteStream data = inviteManager.getData(param.getStream());
            // 回放流
            if (Objects.nonNull(data) && data.getAction().equalsIgnoreCase(GB28181SDPBuilder.Action.PLAY_BACK.getAction())) {
                log.info("[回放流], 发起关闭");
                ToDevice toDevice = data.getToDevice();
                sipMessageTemplate.closeRtp(toDevice, data.getStreamId());
                return HookResultForStreamNoneReader.CLOSE();
            }
        }

        // 代理无人观看
        else if (StringUtils.equalsIgnoreCase(MediaEnum.App.proxy.name(), param.getApp())) {
            // todo 不处理
        }

        return HookResultForStreamNoneReader.SUCCESS();
    }

    @Override
    public void onStreamNotFound(OnStreamNotFoundHookParam param) {
        log.info("on-streamNotFound");
        // 清除缓存
        inviteManager.delData(param.getStream());
    }

    @Override
    public void onServerStarted(ServerNodeConfig param) {
        log.info("on-serverStarted");
    }

    @Override
    public void onSendRtpStopped(OnSendRtpStoppedHookParam param) {
        log.info("on-sendRtpStopped");
    }

    @Override
    public void onRtpServerTimeout(OnRtpServerTimeoutHookParam param) {
        log.info("on-rtpServerTimeout");
    }

    @Override
    public HookResultForOnHttpAccess onHttpAccess(OnHttpAccessParam param) {
        log.info("onHttpAccess");
        return HookResultForOnHttpAccess.SUCCESS();
    }

    @Override
    public HookResultForOnRtspRealm onRtspRealm(OnRtspRealmHookParam param) {
        log.info("onRtspRealm");
        return HookResultForOnRtspRealm.SUCCESS();
    }

    @Override
    public HookResultForOnRtspAuth onRtspAuth(OnRtspAuthHookParam param) {
        log.info("onRtspAuth");
        return HookResultForOnRtspAuth.SUCCESS();
    }

    @Override
    public void onFlowReport(OnFlowReportHookParam param) {
        log.info("onFlowReport");
    }

    @Override
    public void onServerExited(HookParam param) {
        log.info("onServerExited");
        inviteManager.removeAll();
        proxyManager.removeAll();
    }

    @Override
    public void onRecordMp4(OnRecordMp4HookParam param) {
        log.info("「zlm_hook」录制文件生成,{}", param.getStream());
    }


}
